package com.cb2.algorithm.leetcode;

/**
 * <a href='https://leetcode.cn/problems/maximum-points-you-can-obtain-from-cards'>可获得的最大点数(Maximum Points You Can Obtain from Cards)</a>
 * <p>几张卡牌 排成一行，每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。</p>
 * <p>每次行动，你可以从行的开头或者末尾拿一张卡牌，最终你必须正好拿 k 张卡牌。</p>
 * <p>你的点数就是你拿到手中的所有卡牌的点数之和。</p>
 * <p>给你一个整数数组 cardPoints 和整数 k，请你返回可以获得的最大点数。</p>
 *
 * <p>
 * <b>示例：</b>
 * <pre>
 *  示例 1：
 *      输入：cardPoints = [1,2,3,4,5,6,1], k = 3
 *      输出：12
 *      解释：第一次行动，不管拿哪张牌，你的点数总是 1 。但是，先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌，最终点数为 1 + 6 + 5 = 12 。
 *
 * 示例 2：
 *      输入：cardPoints = [2,2,2], k = 2
 *      输出：4
 *      解释：无论你拿起哪两张卡牌，可获得的点数总是 4 。
 *
 * 示例 3：
 *      输入：cardPoints = [9,7,7,9,7,7,9], k = 7
 *      输出：55
 *      解释：你必须拿起所有卡牌，可以获得的点数为所有卡牌的点数之和。
 *
 * 示例 4：
 *      输入：cardPoints = [1,1000,1], k = 1
 *      输出：1
 *      解释：你无法拿到中间那张卡牌，所以可以获得的最大点数为 1 。
 *
 * 示例 5：
 *      输入：cardPoints = [1,79,80,1,1,1,200,1], k = 3
 *      输出：202
 * </pre>
 * </p>
 *
 * <p>
 * <b>提示：</b>
 * <ul>
 *     <li>1 <= cardPoints.length <= 10^5</li>
 *     <li>1 <= cardPoints[i] <= 10^4</li>
 *     <li>1 <= k <= cardPoints.length</li>
 * </ul>
 * </p>
 *
 * @author c2b
 * @since 2025/4/30 16:02
 */
public class LC1423MaximumPointsYouCanObtainFromCards_M {
    static class Solution {

        /**
         * 找出一直从左侧向右取可取到的最右位置。将数组看成循环数组，从该位置开始不断向左移动窗口。
         */
        public int maxScore(int[] cardPoints, int k) {
            int n = cardPoints.length;
            int sum = 0;
            for (int i = 0; i < k; i++) {
                sum += cardPoints[i];
            }
            int res = sum;
            for (int i = k - 1, j = n - 1; i >= 0; i--, j--) {
                sum -= cardPoints[i];
                sum += cardPoints[j];
                res = Math.max(res, sum);
            }
            return res;
        }

        /**
         * 找出一直从右侧向左取可取到的最左位置。将数组看成循环数组，从该位置开始不断向右移动窗口。
         */
        public int maxScore2(int[] cardPoints, int k) {
            int n = cardPoints.length;
            int sum = 0;
            for (int i = n - k; i < n; i++) {
                sum += cardPoints[i % n];
            }
            int res = sum;
            for (int i = n; i < n + k; i++) {
                sum -= cardPoints[(i - k) % n];
                sum += cardPoints[i % n];

                res = Math.max(res, sum);
            }
            return res;
        }
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.maxScore(new int[]{1, 2, 3, 4, 5, 6, 1}, 3));
        System.out.println(solution.maxScore(new int[]{2, 2, 2}, 2));
        System.out.println(solution.maxScore(new int[]{9, 7, 7, 9, 7, 7, 9}, 7));
        System.out.println(solution.maxScore(new int[]{1, 1000, 1}, 1));
        System.out.println(solution.maxScore(new int[]{1, 79, 80, 1, 1, 1, 200, 1}, 3));
    }
}
